﻿#region

using System;
using System.Configuration;
using System.Web;
using BuildMotion.Common.MotionTracker;

#endregion

namespace BuildMotion.MotionTracker
{
    public class MotionTrackerAdaptor : IMotionTrackerRepositoryBase
    {
        #region IMotionTrackerRepositoryBase Members

        /// <summary>
        /// Tracks the request.
        /// </summary>
        /// <param name="application">The application.</param>
        public void TrackRequest(HttpApplication application)
        {
            string trackerId = Guid.NewGuid().ToString();
            this.TrackRequest(application, trackerId, null);
        }

        /// <summary>
        /// Tracks the request.
        /// </summary>
        /// <param name="application">The application.</param>
        /// <param name="trackerId">The tracker id.</param>
        /// <param name="trackerOriginId">The tracker origin id.</param>
        public void TrackRequest(HttpApplication application, string trackerId, string trackerOriginId)
        {
            MotionTrackerModel entityContext = GetTrackerContext();

            #region Create a new Request item;

            var logRequest = new LogRequest();
            logRequest.LogRequestId = Guid.NewGuid();
            logRequest.TrackerId = trackerId;
            logRequest.TrackerOriginId = trackerOriginId;
            logRequest.Timestamp = DateTime.Now;

            entityContext.AddToLogRequest(logRequest);

            #endregion

            #region Add Browser Information;

            var browser = new Browser();
            browser.BrowserId = Guid.NewGuid(); // Add PK value;
            browser.ActiveXControls = application.Request.Browser.ActiveXControls;
            browser.Cookies = application.Request.Browser.Cookies;
            browser.EcmaScriptVersion = application.Request.Browser.EcmaScriptVersion.ToString();
            browser.Frames = application.Request.Browser.Frames;
            browser.IsMobileDevice = application.Request.Browser.IsMobileDevice;
            browser.JScriptVersion = application.Request.Browser.JScriptVersion.ToString();
            browser.MajorVersion = application.Request.Browser.MajorVersion.ToString();
            browser.MinorVersion = application.Request.Browser.MinorVersionString;
            browser.MSDomVersion = application.Request.Browser.MSDomVersion.ToString();
            browser.Name = application.Request.Browser.Browser;
            browser.Platform = application.Request.Browser.Platform;
            browser.RequiresContentTypeMetaTag = application.Request.Browser.RequiresContentTypeMetaTag;
            browser.SupportsCallback = application.Request.Browser.SupportsCallback;
            browser.SupportsRedirectWithCookie = application.Request.Browser.SupportsRedirectWithCookie;
            browser.SupportsXmlHttp = application.Request.Browser.SupportsXmlHttp;
            browser.Type = application.Request.Browser.Type;
            browser.Version = application.Request.Browser.Version;
            browser.W3CDomVersion = application.Request.Browser.W3CDomVersion.ToString();

            entityContext.AddToBrowser(browser);

            #endregion

            #region Add Session Information;
            var session = new Session();
            session.Id = Guid.NewGuid();
            if (application.Session != null)
            {
                session.SessionID = application.Session.SessionID;
                session.IsNewSession = application.Session.IsNewSession;
                session.IsReadOnly = application.Session.IsReadOnly;
                session.IsSynchronized = application.Session.IsSynchronized;
            }
            entityContext.AddToSession(session);

            #endregion

            #region Add Url Information;

            var url = new Url();
            url.UrlId = Guid.NewGuid(); //Add PK value;
            url.AbsoluteUri = application.Request.Url.AbsoluteUri;
            url.Authority = application.Request.Url.Authority;
            url.Host = application.Request.Url.Host;
            url.IsAbsoluteUri = application.Request.Url.IsAbsoluteUri;
            url.IsDefaultPort = application.Request.Url.IsDefaultPort;
            url.OriginalString = application.Request.Url.OriginalString;
            url.PathAndQuery = application.Request.Url.PathAndQuery;
            url.Port = application.Request.Url.Port.ToString();
            url.Scheme = application.Request.Url.Scheme;

            entityContext.AddToUrl(url);

            #endregion

            #region Add UrlReferrer Information;

            var urlReferrer = new UrlReferrer();
            urlReferrer.UrlReferrerId = Guid.NewGuid(); //Add PK value;

            if (application.Request.UrlReferrer != null)
            {
                urlReferrer.AbsoluteUri = application.Request.UrlReferrer.AbsoluteUri;
                urlReferrer.Authority = application.Request.UrlReferrer.Authority;
                urlReferrer.Host = application.Request.UrlReferrer.Host;
                urlReferrer.IsAbsoluteUri = application.Request.UrlReferrer.IsAbsoluteUri;
                urlReferrer.IsDefaultPort = application.Request.UrlReferrer.IsDefaultPort;
                urlReferrer.OriginalString = application.Request.UrlReferrer.OriginalString;
                urlReferrer.PathAndQuery = application.Request.UrlReferrer.PathAndQuery;
                urlReferrer.Port = application.Request.UrlReferrer.Port.ToString();
                urlReferrer.Scheme = application.Request.UrlReferrer.Scheme;
            }

            entityContext.AddToUrlReferrer(urlReferrer);

            #endregion

            #region Add Timestamp Information;

            var timestamp = new Timestamp();
            timestamp.TimestampId = Guid.NewGuid();

            DateTime requestTimestamp = DateTime.Now;
            timestamp.Date = requestTimestamp.Date;
            timestamp.Day = requestTimestamp.Day;
            timestamp.DayOfWeek = requestTimestamp.DayOfWeek.ToString();
            timestamp.DayOfYear = requestTimestamp.DayOfYear;
            timestamp.Hour = requestTimestamp.Hour;
            timestamp.Kind = requestTimestamp.Kind.ToString();
            timestamp.Millisecond = requestTimestamp.Millisecond;
            timestamp.Minute = requestTimestamp.Minute;
            timestamp.Month = requestTimestamp.Month;
            timestamp.Second = requestTimestamp.Second;
            timestamp.Year = requestTimestamp.Year;

            entityContext.AddToTimestamp(timestamp);

            #endregion

            #region LogItem

            var logItem = new LogItem();
            logItem.LogId = Guid.NewGuid();

            // item aggregates;
            logItem.Browser = browser;
            logItem.Headers = application.Request.Headers.ToString();
            logItem.HttpMethod = application.Request.HttpMethod;
            logItem.LogRequest = logRequest;
            logItem.Session = session;
            logItem.Url = url;
            logItem.UrlReferrer = urlReferrer;
            logItem.Timestamp = timestamp;

            // item properties;
            logItem.UserHostAddress = application.Request.UserHostAddress;
            logItem.UserAgent = application.Request.UserAgent;
            logItem.UserHostName = application.Request.UserHostName;
            logItem.PhysicalPath = application.Request.PhysicalPath;
            logItem.RawUrl = application.Request.RawUrl;
            logItem.RequestType = application.Request.RequestType;
            logItem.EncodingName = application.Request.ContentEncoding.ToString();
            logItem.TotalBytes = application.Request.TotalBytes;

            entityContext.AddToLogItem(logItem);

            #endregion

            // Save all information;
            entityContext.SaveChanges();
        }

        #endregion

        /// <summary>
        /// Gets the tracker database context.
        /// </summary>
        /// <returns></returns>
        private static MotionTrackerModel GetTrackerContext()
        {
            // Retrieve the connection string and create the Entity Model Context for Data Access;
            string connectionString = ConfigurationManager.ConnectionStrings["MotionTrackerModel"].ConnectionString;
            var dataContext = new MotionTrackerModel(connectionString);
            return dataContext;
        }
    }
}